package character;

import java.util.ArrayList;

import powers.Power;
import virtualTabletop.Die;
import virtualTabletop.Position;
import virtualTabletop.TargetType;
import Items.Weapon;
import abilities.Abilities;
import abilities.Ability;
import conditionsandeffects.Condition;
import conditionsandeffects.Effect;
import defenses.Defense;
import defenses.Defenses;

/**
 *All characters
 * 
 * @author bjo013
 * 
 */
public abstract class Character
{
	/**
	 *
	 */
	private static final long serialVersionUID = -825460236315548410L;

	protected HitPoints hp;
	protected Abilities abilities;
	protected Defenses defenses;
	protected ArrayList<Power> powers = new ArrayList<Power>();
	protected int speed;
	protected int actionPoints;
	protected int savingThrowBonus;
	protected ArrayList<Aura> auras;
	protected Senses senses;
	protected Size size;
	protected int reach;
	protected ArrayList<Condition> conditions;
	protected ArrayList<Effect> effects;
	protected ArrayList<Resistance> resistances;
	protected Alignment alignment;
	protected int initiativeMod;
	protected int initiative = 0;
	protected TargetType targetType;
	protected Weapon mainweapon;
	protected Position pos;
	protected Character target;
	protected String name;
	protected Boolean alive = true;
	protected Team team;
	protected String sprite;

	/**
	 * Constructor for characters
	 * 
	 * @param hp
	 *            How much hp a character has
	 * @param surgesPrDay
	 *            how many surges a character has
	 * @param used2ndWind
	 *            if the character has used 2nd wind
	 * @param abilities
	 *            the abilities of the character
	 * @param AC
	 *            the AC of the character
	 * @param Fort
	 *            the fortitude save of the character
	 * @param Ref
	 *            the reflex save of the character
	 * @param Will
	 *            the will save of the character
	 * @param powers
	 *            the powers of the character
	 * @param speed
	 *            the speed of the character in squares
	 * @param actionPoints
	 *            the action points the character has
	 * @param savingThrowBonus
	 *            the saving throw bonus a character has
	 * @param size
	 *            the size of a character
	 * @param resistances
	 *            the resistances of a character
	 * @param alignment
	 *            the alignment of a character
	 * @param initiative
	 *            the initiative the character has thrown
	 * @param targetType
	 *            the targettype of a character
	 * @param mainweapon
	 *            the characters main weapon.
	 * @param pos
	 *            the position of a character
	 * @param name
	 *            the name of the character
	 * @param team
	 *            the team of the character
	 * @param sprite
	 *            the sprite of the character
	 */
	public Character(int hp, int surgesPrDay, Abilities abilities, int[] AC,
			int[] Fort, int[] Ref, int[] Will, ArrayList<Power> powers,
			int speed, int actionPoints, int savingThrowBonus, Size size,
			ArrayList<Resistance> resistances, Alignment alignment,
			int initiative, TargetType targetType, Weapon mainweapon,
			Position pos, String name, Team team, String sprite)
	{
		this.hp = new HitPoints(hp, surgesPrDay);
		this.abilities = abilities;
		defenses = new Defenses(AC, Fort, Ref, Will);
		this.powers = powers;
		this.speed = speed;
		this.actionPoints = actionPoints;
		this.savingThrowBonus = savingThrowBonus;
		this.size = size;
		this.resistances = resistances;
		this.alignment = alignment;
		initiativeMod = initiative;
		this.targetType = targetType;
		this.mainweapon = mainweapon;
		this.pos = pos;
		this.name = name;
		this.team = team;

		this.sprite = sprite;
	}

	/**
	 * get the initiative bonus
	 * 
	 * @return initiative modifier
	 */
	public int getInitiativeBonus()
	{
		return initiativeMod;
	}

	/**
	 * Returns the initiative before being set, always 0.
	 * 
	 * @return initiative
	 */
	public int getInitiative()
	{
		return initiative;
	}

	/**
	 * sets the initiative via a random dieroll + initiative modifier.
	 */
	public void setInitiative()
	{
		initiative = Die.d20.roll() + initiativeMod;
	}

	/**
	 * set the target of the character
	 * 
	 * @param character
	 *            a different character
	 */
	public void setTarget(Character character)
	{
		target = character;
	}

	/**
	 * gets the target
	 * 
	 * @return target
	 */
	public Character getTarget()
	{
		return target;
	}

	/**
	 * get all the powers a character has
	 * 
	 * @return all powers
	 */
	public ArrayList<Power> getPowers()
	{
		return powers;
	}

	/**
	 * gets the value of a spesific defense
	 * 
	 * @param defense
	 *            a spesific defense.
	 * @return defense score
	 */
	public int getDefense(Defense defense)
	{
		int defValue;
		switch (defense)
		{
		case AC:
			defValue = defenses.getAC();
			break;
		case Fort:
			defValue = defenses.getFort();
			break;
		case Ref:
			defValue = defenses.getRef();
			break;
		case Will:
			defValue = defenses.getWill();
			break;
		default:
			defValue = 0;
		}

		return defValue;
	}

	/**
	 * Modifies the character hp
	 * 
	 * @param dmg
	 *            The damage taken
	 * @return current hp
	 */
	public int takeDamage(int dmg)
	{
		hp.takeDamage(dmg);
		return hp.getCurrentHP();
	}

	/**
	 * get the name of the character
	 * 
	 * @return name
	 */
	public String getName()
	{
		return name;
	}

	/**
	 * gets current hp
	 * 
	 * @return current hp
	 */
	public int getHP()
	{
		return hp.getCurrentHP();
	}

	/**
	 * gets the modifier of the stat.
	 * 
	 * @param ability
	 *            the ability to get the modifier from
	 * @return ability modifier
	 */
	public int getStatMod(Ability ability)
	{
		return abilities.getStatMod(ability);
	}

	/**
	 * gets the main weapon
	 * 
	 * @return main weapon
	 */
	public Weapon getWeapon()
	{
		return mainweapon;
	}

	/**
	 * sets the character to dead
	 */
	public void setDead()
	{
		alive = false;
	}

	/**
	 * checks if the character is alive
	 * 
	 * @return true if alive, false if dead
	 */
	public Boolean isAlive()
	{
		return alive;
	}

	/**
	 * returns characters x position
	 * 
	 * @return x-position
	 */
	public int getX()
	{
		return pos.getX();
	}

	/**
	 * returns characters y position
	 * 
	 * @return y-position
	 */
	public int getY()
	{
		return pos.getY();
	}

	/**
	 * gets x,y position of character
	 * 
	 * @return Position x,y
	 */
	public Position getPosition()
	{
		return pos;
	}

	/**
	 * returns character speed in squares
	 * 
	 * @return number of squares
	 */
	public int getSpeed()
	{
		return speed;
	}

	/**
	 * returns character team
	 * 
	 * @return team
	 */
	public Team getTeam()
	{
		return team;
	}

	/**
	 * returns a string of the path to the sprite
	 * 
	 * @return String to path
	 */
	public String getSprite()
	{
		return sprite;
	}

	@Override
	public String toString()
	{
		String s = new String();
		s += "Name: " + name + "\n";
		s += "Size: " + size + "\n";
		s += "Initiative: " + initiativeMod + "\n";
		s += hp + "\n";
		s += "Speed: " + speed + "\n";
		s += "\n";
		s += abilities + "\n";
		s += "\n";
		s += defenses + "\n";
		s += "\n";
		s += mainweapon;
		s += "\n";
		if (!powers.isEmpty())
		{
			s += "\nPowers:\n";
			for (Power p : powers)
			{
				s += p + "\n\n";
			}
		}
		return s;

	}
}

/*
 * 
 * protected int actionPoints; protected int savingThrowBonus; protected
 * ArrayList<Aura> auras; protected Senses senses; protected int reach;
 * protected ArrayList<Condition> conditions; protected ArrayList<Effect>
 * effects; protected ArrayList<Resistance> resistances; protected Alignment
 * alignment; protected TargetType targetType; protected Position pos; protected
 * Character target; protected Boolean alive = true; protected Team team;
 * protected String sprite;
 */
